package menu

import (
	"context"

	v1 "gitee.com/liangziyisheng/caas-platform-mc/api/menu/v1"
	"gitee.com/liangziyisheng/caas-platform-mc/internal/consts"
	"gitee.com/liangziyisheng/caas-platform-mc/internal/dao"
	"gitee.com/liangziyisheng/caas-platform-mc/internal/service"

	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/glog"
)

type sMenu struct{}

var l = g.Log("logger for Menu")

func New() *sMenu {
	return &sMenu{}
}

func init() {
	l.SetFlags(glog.F_FILE_LONG)
	service.RegisterMenu(New())
}

func (s *sMenu) List(ctx context.Context, in *v1.ListInput) (out *v1.ListOutput, err error) {
	out = &v1.ListOutput{}
	err = dao.AppMenu.Ctx(ctx).Where(dao.AppMenu.Columns().AppCode, in.AppCode).OrderAsc(dao.AppMenu.Columns().Sort).Scan(&out.Data)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.ListFailed, in))
	}

	return out, nil
}
func (s *sMenu) ListApp(ctx context.Context) (out *v1.AppOutput, err error) {
	out = &v1.AppOutput{}
	err = dao.AppMenu.Ctx(ctx).Where(dao.AppMenu.Columns().Type, consts.MenuTypes[0].Value).Scan(&out.Data)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(consts.ListFailed)
	}

	return out, nil
}
func (s *sMenu) Info(ctx context.Context, in *v1.InfoInput) (out *v1.InfoOutput, err error) {
	return nil, nil
}

func (s *sMenu) Add(ctx context.Context, in *v1.AddInput) (out *v1.AddOutput, err error) {
	// parent首先必需存在
	if in.Type != consts.MenuTypes[0].Value {
		rows, err := dao.AppMenu.Ctx(ctx).Where(dao.AppMenu.Columns().Id, in.Parent).Count()
		if err != nil {
			l.Error(ctx, err)
			return nil, gerror.NewCode(gcode.WithCode(consts.QueryAppMenuFailed, in.Parent))
		}
		if rows != 1 {
			l.Error(ctx, err)
			return nil, gerror.NewCode(gcode.WithCode(consts.AppMenuNotExist, in.Parent))
		}
	}
	id, err := dao.AppMenu.Ctx(ctx).InsertAndGetId(in.AppMenu)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.AddFailed, in.AppMenu))
	}
	return &v1.AddOutput{Id: id}, nil
}

func (s *sMenu) Delete(ctx context.Context, in *v1.DeleteInput) (out *v1.DeleteOutput, err error) {
	// 先检查是否存在子菜单
	rows, err := dao.AppMenu.Ctx(ctx).Where(dao.AppMenu.Columns().Parent, in.Id).Count()
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.QueryAppMenuFailed, in.Id))
	}
	if rows > 0 {
		return nil, gerror.NewCode(consts.MenuHasChildrenNode)
	}
	// 再检查是否存在权限
	rows, err = dao.Permission.Ctx(ctx).Where(dao.Permission.Columns().MenuId, in.Id).Count()
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.QueryAppPermissionByMenuFailed, in.Id))
	}
	if rows > 0 {
		return nil, gerror.NewCode(consts.MenuHasChildrenPermission)
	}
	// 最后删除
	rs, err := dao.AppMenu.Ctx(ctx).Where(dao.AppMenu.Columns().Id, in.Id).Delete()
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.DeleteFailed, in.Id))
	}
	out = &v1.DeleteOutput{}
	if out.Rows, err = rs.RowsAffected(); err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.DeleteFailed, in.Id))
	}
	if out.Rows == 0 {
		return nil, gerror.NewCode(gcode.WithCode(consts.DeleteFailed, in.Id))
	}
	return out, nil
}

func (s *sMenu) Update(ctx context.Context, in *v1.UpdateInput) (out *v1.UpdateOutput, err error) {
	out = &v1.UpdateOutput{}
	out.Rows, err = dao.AppMenu.Ctx(ctx).Data(in.AppMenu).Where(dao.AppMenu.Columns().Id, in.Id).UpdateAndGetAffected()
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.UpdateFailed, in.AppMenu))
	}
	if out.Rows == 0 {
		return nil, gerror.NewCode(gcode.WithCode(consts.UpdateFailed, in.Id))
	}
	return out, nil
}
